package com.paul.log.aop;


import com.paul.common.annotation.NoRepeatSubmit;
import com.paul.common.constant.RedisKeyConst;
import com.paul.common.exception.BusinessException;
import com.paul.common.exception.ExceptionCode;
import com.paul.common.utils.HttpContextUtil;
import com.paul.common.utils.PaulUtil;
import com.paul.common.utils.MD5Util;
import com.paul.redis.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;


/**
 * @author ：zmk
 * @date ：Created in 2021/11/11 10:34
 * @description：防重复提交
 */
@Aspect
@Component
public class NoRepeatSubmitAop {

    private final static Logger logger = LoggerFactory.getLogger(NoRepeatSubmitAop.class);

    @Autowired
    private RedisUtil redisUtil;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointCut(NoRepeatSubmit noRepeatSubmit) {
    }


    @Around("pointCut(nrs)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) throws Throwable {
        ServletRequestAttributes attributes = HttpContextUtil.getRequestAttributes();

        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String token = request.getHeader("Authorization");
        if (StringUtils.isBlank(token)) {
            token = Objects.requireNonNull(attributes).getSessionId();
        }
        String path = request.getServletPath();
        String key = getKey(token, path);
        //String clientId = getClientId();

        // 如果缓存中有这个url视为重复提交
        String reqKey = RedisKeyConst.REQUEST_ID + key;
        if (redisUtil.increment(reqKey, 1) > 1) {
            throw new BusinessException(ExceptionCode.REPEATED_REQUESTS.value(), "请求太频繁,请稍后再试！");
        }
        redisUtil.expire(reqKey, nrs.value());
        return pjp.proceed();

    }

    private String getKey(String token, String path) {
        return MD5Util.getMD5(token + path);
    }

    private String getClientId() {
        return PaulUtil.getUUIDStr();
    }
}
